package com.test.dubbo;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;

import java.util.HashMap;
import java.util.Map;

/**
 * dubbo接口泛化调用
 * 参数说明：
 *  如果参数为基本类型或者 Date,List,Map 等，则不需要转换，直接调用。
 *  如果参数为其他 POJO，则使用 Map 代替。
 */
public class GenericServiceMain {

    private static String zk = "zookeeper://10.70.5.11:2181?backup=10.70.5.12:2181,10.70.5.13:2181";
    private static GenericService genericService;

    public static void main(String[] args) throws Exception {
        invoke("com.user.point.emp.EmpService", "1.0.0", "getEmpInfoByCode", new String[]{"java.lang.String"}, new Object[]{"H333222"});
//        invoke("com.customerPublic.point.cust.ICustomerPublicApiService", "1.0.0", "getTimeOfFirstLoginJF", new String[]{"java.lang.Long"}, new Object[]{529751});
//
//        Map<String, Object> param = new HashMap();
//        param.put("customerNo", 688494L);
//        param.put("bankCardNo", "6230229266709169");
//        param.put("bankCardType", 0);
//        invoke("com.customerPublic.point.cust.ICustomerPublicApiService", "1.0.0", "getBankCardInfo", new String[]{"com.customerPublic.entity.AccountBankRequest"}, new Object[]{param});

    }

    public static void invoke(String interfaceName, String version, String methodName, String[] parameterTypes, Object[] parameters) {
        //创建ApplicationConfig
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("generic-call-consumer");
        //创建注册中心配置
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress(zk);
        //创建服务引用配置
        ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<>();
        //设置接口
        referenceConfig.setInterface(interfaceName);
        referenceConfig.setVersion(version);
        applicationConfig.setRegistry(registryConfig);
        referenceConfig.setApplication(applicationConfig);
        //重点：设置为泛化调用
        //注：不再推荐使用参数为布尔值的setGeneric函数
        //应该使用referenceConfig.setGeneric("true")代替
        referenceConfig.setGeneric(true);
        //设置异步，不必须，根据业务而定。
        // referenceConfig.setAsync(true);
        //设置超时时间
        referenceConfig.setTimeout(7000);
        //获取服务，由于是泛化调用，所以获取的一定是GenericService类型
        genericService = referenceConfig.get();
        //使用GenericService类对象的$invoke方法可以代替原方法使用
        //第一个参数是需要调用的方法名
        //第二个参数是需要调用的方法的参数类型数组，为String数组，里面存入参数的全类名。
        //第三个参数是需要调用的方法的参数数组，为Object数组，里面存入需要的参数。
        Object result = genericService.$invoke(methodName, parameterTypes, parameters);
        System.out.println("***** " + methodName + " return: " + result);
        /*//使用CountDownLatch，如果使用同步调用则不需要这么做。
        CountDownLatch latch = new CountDownLatch(1);
        //获取结果
        CompletableFuture<String> future = RpcContext.getContext().getCompletableFuture();
        future.whenComplete((value, t) -> {
            System.err.println("invokeSayHello(whenComplete): " + value);
            latch.countDown();
        });
        //打印结果
        System.err.println("invokeSayHello(return): " + result);
        latch.await();*/
    }
}
